package cn.fanyamin.dao.ibatis;

import java.sql.SQLException;
import java.util.List;


import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import cn.fanyamin.business.ICRUD;
import cn.fanyamin.business.NoResultsFoundException;

import com.ibatis.sqlmap.client.SqlMapExecutor;

public class CRUDDao<K, T> extends SqlMapClientDaoSupport implements
		ICRUD<K, T> {

	protected String RETRIEVE_SQLID = "retrieve";
	protected String CREATE_SQLID = "create";
	protected String UPDATE_SQLID = "update";
	protected String DELETE_SQLID = "delete";
	protected String FIND_SQLID = "find";
	protected String LIST_SQLID = "list";
	protected String GETLIST_SQLID = "getListOf";

	public CRUDDao() {

	}

	public CRUDDao(String domainName) {
		setSQLID(domainName);
	}

	protected void setSQLID(String domainName) {
		RETRIEVE_SQLID = "retrieve" + domainName;
		CREATE_SQLID = "create" + domainName;
		UPDATE_SQLID = "update" + domainName;
		DELETE_SQLID = "delete" + domainName;
		FIND_SQLID = "find" + domainName;
		LIST_SQLID = "list" + domainName;
		GETLIST_SQLID = "getListOf" + domainName;
	}

	public K create(T t) {
		K ret = (K) getSqlMapClientTemplate().insert(CREATE_SQLID, t);

		return ret;
	}

	public int delete(K id) {
		return getSqlMapClientTemplate().delete(DELETE_SQLID, id);

	}

	public List<T> find(T t) {
		List<T> list = (List<T>) getSqlMapClientTemplate().queryForList(
				FIND_SQLID, t);
		if (null == list) {
			throw new NoResultsFoundException(FIND_SQLID + " for " + t);
		}

		return list;
	}

	public List<T> list() {
		List<T> list = (List<T>) getSqlMapClientTemplate().queryForList(
				LIST_SQLID, null);
		if (null == list) {
			throw new NoResultsFoundException(LIST_SQLID);
		}

		return list;
	}

	public List<T> list(K id) {
        List<T> list = (List<T>) getSqlMapClientTemplate().queryForList(
                GETLIST_SQLID, id);
        if (null == list) {
            throw new NoResultsFoundException(GETLIST_SQLID);
        }

        return list;
    }
	
	public T retrieve(K id) {
		T retTask = (T) getSqlMapClientTemplate().queryForObject(
				RETRIEVE_SQLID, id);

		if (null == retTask) {
			throw new NoResultsFoundException(RETRIEVE_SQLID + ", id=" + id);
		}

		return retTask;
	}

	public int update(T t) {
		return getSqlMapClientTemplate().update(UPDATE_SQLID, t);
	}

	public void batchInsert(final List<T> list) {
		SqlMapClientCallback callback = new SqlMapClientCallback() {
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();
				for (T member : list) {
					executor.insert(CREATE_SQLID, member);
				}
				executor.executeBatch();
				return null;
			}
		};
		this.getSqlMapClientTemplate().execute(callback);
	}

	public void batchUpdate(final List<T> list) {
		SqlMapClientCallback callback = new SqlMapClientCallback() {
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();
				for (T member : list) {
					executor.update(UPDATE_SQLID, member);
				}
				executor.executeBatch();
				return null;
			}
		};
		this.getSqlMapClientTemplate().execute(callback);
	}

	public void batchDelete(final List<K> list) {
		SqlMapClientCallback callback = new SqlMapClientCallback() {
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();
				for (K member : list) {
					executor.delete(DELETE_SQLID, member);
				}
				executor.executeBatch();
				return null;
			}
		};
		this.getSqlMapClientTemplate().execute(callback);
	}

}
